﻿#ifndef PST_INFOMATIONCURVE2DBASICAL_H
#define PST_INFOMATIONCURVE2DBASICAL_H

#include <QObject>
#include <QList>
#include <QPair>
#include <QSet>
#include <QDomElement>
#include <QDomDocument>
#include <QDomAttr>
#include <tuple>
#include <QVector>
#include <array>
#include <qcustomplot.h>
#include "PostEnumType.h"

namespace
{
    bool areVectorsEqual(const QSet<double>& vec1, const QSet<double>& vec2)
    {
        // 首先检查大小
        if (vec1.size() != vec2.size())
        {
            return false; // 大小不相等直接返回 false
        }

        // 使用 std::equal 比较内容
        return std::equal(vec1.begin(), vec1.end(), vec2.begin());
    }

    // 查找多个 QVector 的公共字符串
    QList<QString> findCommonStrings(const QList<QVector<QString>>& vectors)
    {
        // 如果没有QVector，则返回空列表
        if (vectors.isEmpty())
        {
            return QList<QString>();
        }

        // 使用第一个QVector作为基准集
        QSet<QString> commonStrings = QSet<QString>::fromList(QList<QString>::fromVector(vectors[0]));

        // 迭代其他QVector
        for (int i = 1; i < vectors.size(); ++i)
        {
            QSet<QString> currentSet = QSet<QString>::fromList(QList<QString>::fromVector(vectors[i]));
            commonStrings.intersect(currentSet); // 找到交集
        }

        // 将结果转换为QList并返回
        return commonStrings.toList();
    }
} // namespace

namespace pst
{
    class Graph2DWindowBase;
    class TextFileParser;
    class LineChartCoordinateSettingData;
    class Style2D_DataProperty;
    class LineChartCenterSettingData;
    class PolarCoordinateGraphCenterSettingData;
    class DataHeatGraph2DSettings;

    class InfomationCurve2DBasical;
    using Info2DPointer = QSharedPointer<InfomationCurve2DBasical>;

    class InfomationCurve2DBasical : public QObject
    {
        Q_OBJECT
    public:
        InfomationCurve2DBasical(QObject* parent = nullptr)
            : QObject(parent)
        {
        }

        static bool getCommonData(const QList<Info2DPointer>& dataList, Info2DPointer& commonInfo);

        InfomationCurve2DBasical operator=(const InfomationCurve2DBasical& other)
        {
            this->m_informationID = other.m_informationID;
            this->m_isCurveVisible = other.m_isCurveVisible;
            this->m_lineChartCurveEditParameters = other.m_lineChartCurveEditParameters;
            this->m_isMuti = other.m_isMuti;
            this->m_x = other.m_x;
            this->m_y = other.m_y;
            this->m_addedGraph = other.m_addedGraph;
            this->m_reader = other.m_reader;
            this->m_scanParaIndex = other.m_scanParaIndex;
            this->m_secondScanParaIndex = other.m_secondScanParaIndex;
            this->m_curveLineAddress = other.m_curveLineAddress;
            this->m_otherKeyData = other.m_otherKeyData;
            this->m_valueIndex = other.m_valueIndex;
            this->m_valueComponent = other.m_valueComponent;
            this->m_isNormalized = other.m_isNormalized;
            this->m_isDB = other.m_isDB;
            this->m_isDBState = other.m_isDBState;
            this->m_scanParaName = other.m_scanParaName;
            this->m_secondScanParaName = other.m_secondScanParaName;
            this->m_graphType = other.m_graphType;
            this->m_isNewData = other.m_isNewData;
            this->m_isOnlyShow = other.m_isOnlyShow;
            this->m_animationDataList = other.m_animationDataList;
            this->m_enableMathematicalOperations = other.m_enableMathematicalOperations;
            this->m_calculationFormula = other.m_calculationFormula;
            this->m_curveName = other.m_curveName;
            this->m_isImport = other.m_isImport;
            this->m_geometryFileName = other.m_geometryFileName;
            this->m_dataSources = other.m_dataSources;
            this->m_fieldType = other.m_fieldType;
            this->m_unit = other.m_unit;
            this->m_VarValueList = other.m_VarValueList;
            this->m_lastFrameIndexBeforeExportAnimation = other.m_lastFrameIndexBeforeExportAnimation;
            this->m_projectTreeSourceItem = other.m_projectTreeSourceItem;
            this->m_xAxisType = other.m_xAxisType;
            this->m_xAxisUnit = other.m_xAxisUnit;
            this->m_yAxisUnit = other.m_yAxisUnit;
            this->m_isFromStandardFile = other.m_isFromStandardFile;
            return *this;
        }

        InfomationCurve2DBasical(const InfomationCurve2DBasical& other)
        {
            this->m_informationID = other.m_informationID;
            this->m_isCurveVisible = other.m_isCurveVisible;
            this->m_lineChartCurveEditParameters = other.m_lineChartCurveEditParameters;
            this->m_isMuti = other.m_isMuti;
            this->m_x = other.m_x;
            this->m_y = other.m_y;
            this->m_addedGraph = other.m_addedGraph;
            this->m_reader = other.m_reader;
            this->m_scanParaIndex = other.m_scanParaIndex;
            this->m_secondScanParaIndex = other.m_secondScanParaIndex;
            this->m_curveLineAddress = other.m_curveLineAddress;
            this->m_otherKeyData = other.m_otherKeyData;
            this->m_valueIndex = other.m_valueIndex;
            this->m_valueComponent = other.m_valueComponent;
            this->m_isNormalized = other.m_isNormalized;
            this->m_isDB = other.m_isDB;
            this->m_isDBState = other.m_isDBState;
            this->m_scanParaName = other.m_scanParaName;
            this->m_secondScanParaName = other.m_secondScanParaName;
            this->m_graphType = other.m_graphType;
            this->m_isNewData = other.m_isNewData;
            this->m_isOnlyShow = other.m_isOnlyShow;
            this->m_animationDataList = other.m_animationDataList;
            this->m_enableMathematicalOperations = other.m_enableMathematicalOperations;
            this->m_calculationFormula = other.m_calculationFormula;
            this->m_curveName = other.m_curveName;
            this->m_isImport = other.m_isImport;
            this->m_geometryFileName = other.m_geometryFileName;
            this->m_dataSources = other.m_dataSources;
            this->m_fieldType = other.m_fieldType;
            this->m_unit = other.m_unit;
            this->m_VarValueList = other.m_VarValueList;
            this->m_lastFrameIndexBeforeExportAnimation = other.m_lastFrameIndexBeforeExportAnimation;
            this->m_projectTreeSourceItem = other.m_projectTreeSourceItem;

            this->m_xAxisType = other.m_xAxisType;
            this->m_xAxisUnit = other.m_xAxisUnit;
            this->m_yAxisUnit = other.m_yAxisUnit;
            this->m_isFromStandardFile = other.m_isFromStandardFile;
        }

        // 重载 == 操作符
        bool operator==(const InfomationCurve2DBasical& other) const
        {
            return m_informationID == other.m_informationID
                && m_isCurveVisible == other.m_isCurveVisible
                && m_lineChartCurveEditParameters == other.m_lineChartCurveEditParameters
                && m_isMuti == other.m_isMuti
                && m_x == other.m_x && m_y == other.m_y
                && m_scanParaName == other.m_scanParaName
                && m_secondScanParaName == other.m_secondScanParaName
                && m_addedGraph == other.m_addedGraph
                && m_curveLineAddress == other.m_curveLineAddress
                && m_reader == other.m_reader
                && m_scanParaIndex == other.m_scanParaIndex
                && m_secondScanParaIndex == other.m_secondScanParaIndex
                && m_commonFixedNames == other.m_commonFixedNames
                && m_otherKeyData == other.m_otherKeyData
                && m_valueIndex == other.m_valueIndex
                && m_valueComponent == other.m_valueComponent
                && m_isNormalized == other.m_isNormalized
                && m_isDB == other.m_isDB && m_isDBState == other.m_isDBState
                && m_graphType == other.m_graphType
                && m_isNewData == other.m_isNewData
                && m_isOnlyShow == other.m_isOnlyShow
                && m_animationDataList == other.m_animationDataList
                && m_currentAnimationIndex == other.m_currentAnimationIndex
                && m_enableMathematicalOperations == other.m_enableMathematicalOperations
                && m_calculationFormula == other.m_calculationFormula
                && m_curveName == other.m_curveName && m_isImport == other.m_isImport
                && m_geometryFileName == other.m_geometryFileName
                && m_dataSources == other.m_dataSources
                && m_fieldType == other.m_fieldType && m_unit == other.m_unit
                && m_VarValueList == other.m_VarValueList
                && m_lastFrameIndexBeforeExportAnimation == other.m_lastFrameIndexBeforeExportAnimation
                && m_projectTreeSourceItem == other.m_projectTreeSourceItem
                && m_isFromStandardFile == other.m_isFromStandardFile;
        }

        bool operator!=(const InfomationCurve2DBasical& other) const
        {
            return !(*this == other);
        }

        virtual ~InfomationCurve2DBasical() {};

        // 是否有公共的扫描参数, 单个文件默认有，
        // 当本类当作多个类的交集时，用于判断是否有公共的扫描参数
        // void setHasCommonScanParameter(bool hasCommon) { m_hasCommonScanParameter = hasCommon; }
        // bool getHasCommonScanParameter() const { return m_hasCommonScanParameter; }

        // void setIsAllOtherKeySame(bool isSame) { m_isAllOtherKeySame = isSame; }
        // bool getIsAllOtherKeySame() const { return m_isAllOtherKeySame; }

        // void setValueIndexSame(bool isSame) { m_isValueIndexSame = isSame; }
        // bool getValueIndexSame() const { return m_isValueIndexSame; }

        // void setIsAllNormalized(int isNormalized) { m_isAllNormalized = isNormalized; }
        // int getIsAllNormalized() const { return m_isAllNormalized; }

        // void setIsAllDB(int isDB) { m_isAllDB = isDB; }
        // int getIsAllDB() const { return m_isAllDB; }
        inline void setInformationID(int infoID) { m_informationID = infoID; }
        inline int getInformationID() const { return m_informationID; }

        inline void setIsCurveVisible(bool isCurveVisible) { m_isCurveVisible = isCurveVisible; }
        inline bool getIsCurveVisible() const { return m_isCurveVisible; }

        inline void setLineChartCurveEditParameters(const QString& lineChartCurveEditParameters) { m_lineChartCurveEditParameters = lineChartCurveEditParameters; }
        inline QString getLineChartCurveEditParameters() const { return m_lineChartCurveEditParameters; }

        inline void setIsMuti(bool isMuti) { m_isMuti = isMuti; }
        inline bool getIsMuti() const { return m_isMuti; }

        // 传入标题名称和数据
        inline void setXData(const QPair<QString, QVector<double>>& x) { m_x = x; }
        inline QPair<QString, QVector<double>> getXData() const { return m_x; }
        inline QPair<QString, QVector<double>>* getXDataPointer() { return &m_x; }

        // 传入标题名称和数据
        inline void setYData(const QPair<QString, QVector<double>>& y) { m_y = y; }
        inline QPair<QString, QVector<double>> getYData() const { return m_y; }
        inline QPair<QString, QVector<double>>* getYDataPointer() { return &m_y; }

        inline void setCurveLineAddress(QCPLayerable* address) { m_curveLineAddress = address; }
        inline QCPLayerable* getCurveLineAddress() const { return m_curveLineAddress; }

        inline void setGraph(Graph2DWindowBase* graph) { m_addedGraph = graph; }
        inline Graph2DWindowBase* getGraph() const { return m_addedGraph; }

        inline void setReader(TextFileParser* reader) { m_reader = reader; }
        inline TextFileParser* getReader() const { return m_reader; }

        inline void setScanParameterName(const QString& name) { m_scanParaName = name; }
        inline QString getScanParameterName() const { return m_scanParaName; }

        inline void setScanParameterIndex(int index) { m_scanParaIndex = index; }
        inline int getScanParameterIndex() const { return m_scanParaIndex; }

        inline void setSecondScanParameterName(const QString& name) { m_secondScanParaName = name; }
        inline QString getSecondScanParameterName() const { return m_secondScanParaName; }

        inline void setSecondScanParameterIndex(int index) { m_secondScanParaIndex = index; }
        inline int getSecondScanParameterIndex() const { return m_secondScanParaIndex; }

        /// @brief 获取公共的可用作固定轴显示的列名称 只在多个曲线时使用
        inline void setCommonFixedNames(const QList<QString>& names) { m_commonFixedNames = names; }
        inline QList<QString> getCommonFixedNames() const { return m_commonFixedNames; }

        inline void setOtherKeyData(const QVector<double>& data) { m_otherKeyData = data; }
        inline QVector<double> getOtherKeyData() const { return m_otherKeyData; }
        inline QVector<double>* getOtherKeyDataPoinyer() { return &m_otherKeyData; }

        inline void setValueIndex(int index) { m_valueIndex = index; }
        inline int getValueIndex() const { return m_valueIndex; }

        inline void setValueComponent(int component) { m_valueComponent = component; }
        inline int getValueComponent() const { return m_valueComponent; }

        inline void setIsNormalized(int isNormalized) { m_isNormalized = isNormalized; }
        inline int getIsNormalized() const { return m_isNormalized; }

        inline void setIsDB(int isDB) { m_isDB = isDB; }
        inline int getIsDB() const { return m_isDB; }

        inline void setIsDBState(int isDBState) { m_isDBState = isDBState; }
        inline int getIsDBState() const { return m_isDBState; }

        inline void setGraphType(GraphType graphType) { m_graphType = graphType; }
        inline GraphType getGraphType() const { return m_graphType; }

        inline void setIsNewData(bool isNewData) { m_isNewData = isNewData; }
        inline bool getIsNewData() const { return m_isNewData; }

        inline void setIsOnlyShow(bool isOnlyShow) { m_isOnlyShow = isOnlyShow; }
        inline bool getIsOnlyShow() const { return m_isOnlyShow; }

        inline void setAnimationDataList(const QVector<std::array<QVector<double>, 3>>& list) { m_animationDataList = list; }
        QVector<std::array<QVector<double>, 3>> getAnimationDataList() const { return m_animationDataList; }

        inline void setCurrentAnimationIndex(int index) { m_currentAnimationIndex = index; }
        int getCurrentAnimationIndex() const { return m_currentAnimationIndex; }

        inline void enableMathematicalOperations(bool isMathematicalOperations) { m_enableMathematicalOperations = isMathematicalOperations; }
        inline bool getIsMathematicalOperations() const { return m_enableMathematicalOperations; }

        inline void setCalculationFormula(const QString& calculationFormula) { m_calculationFormula = calculationFormula; }
        inline QString getCalculationFormula() const { return m_calculationFormula; }

        inline void setCurveName(const QString& name) { m_curveName = name; }
        inline QString getCurveName() const { return m_curveName; }

        inline void setIsImport(bool isImport) { m_isImport = isImport; }
        inline QString getIsImport() const { return m_isImport; }

        inline void setGeometryFileName(const QStringList& geometryFileName) { m_geometryFileName = geometryFileName; }
        inline QStringList getGeometryFileName() const { return m_geometryFileName; }

        inline void setDataSources(const QString& dataSources) { m_dataSources = dataSources; }
        inline QString getDataSources() const { return m_dataSources; }

        inline void setStandardCurveParserFileName(const QString& standardCurveParserFileName) { m_standardCurveParserFileName = standardCurveParserFileName; }
        inline QString getStandardCurveParserFileName() const { return m_standardCurveParserFileName; }

        inline void setFieldType(int fieldType) { m_fieldType = fieldType; }
        inline int getFieldType() const { return m_fieldType; }

        inline void setUnit(const QString& unit) { m_unit = unit; }
        inline QString getUnit() const { return m_unit; }

        inline void setVarValueList(const QList<double>& varValueList) { m_VarValueList = varValueList; }
        inline QList<double> getVarValueList() const { return m_VarValueList; }

        inline void setLastFrameIndexBeforeExportAnimation(int index) { m_lastFrameIndexBeforeExportAnimation = index; }
        inline int getLastFrameIndexBeforeExportAnimation() const { return m_lastFrameIndexBeforeExportAnimation; }

        // 设置item
        inline void setProjectTreeSourceItem(QStandardItem* item) { this->m_projectTreeSourceItem = item; }
        inline QStandardItem* getProjectTreeSourceItem() const { return this->m_projectTreeSourceItem; }

        /// @brief 侧边栏名称列表对应的item
        /// @param item 
        inline void setSidebarItem(QStandardItem* item) { this->m_sidebarItem = item; }
        inline QStandardItem* getSidebarItem() const { return this->m_sidebarItem; }

        //inline QString getOldXAxisUnit() { return this->m_oldXAxisUnit; }
        //inline void setOldXAxisUnit(const QString& unit) { this->m_oldXAxisUnit = unit; }

        //inline QString getOldYAxisUnit() { return this->m_oldYAxisUnit; }
        //inline void setOldYAxisUnit(const QString& unit) { this->m_oldYAxisUnit = unit; }

        /// @brief 文件写出至工程文件
        QDomElement& writeToProjectFile(QDomDocument* doc, QDomElement* element, GraphType graphType, bool isdiso = false);
        /// @brief 从工程文件读入数据
        void readFromProjectFile(QDomElement* element, GraphType graphType, bool isdiso = false);

        void setIsFromStandardFile(bool isFromStandardFile) { this->m_isFromStandardFile = isFromStandardFile; }
        bool getIsFromStandardFile() const { return this->m_isFromStandardFile; }
    protected:
        // 当本类当作多个类的交集时，用于判断并存储信息
        // 是否有公共的扫描参数, 单个文件默认有，
        // bool m_hasCommonScanParameter{ true };
        // bool m_isAllOtherKeySame{ true };
        // bool m_isValueIndexSame{ true };
        ////是否取归一化，- 1：未定义；0，没有取；其他：取了归一化
        // int m_isAllNormalized{ 0 };
        ////是否取对数，-1：未定义；0，没有取；其他：取了归一化
        // int m_isAllDB{ 0 };
        QString m_lineChartCurveEditParameters{}; // 编辑曲线时的参数
        int m_informationID{0};//一条曲线对应一个info
        bool m_isCurveVisible{true}; // 是否显示曲线
        bool m_isMuti{false}; // 是否是多个曲线
        // 原始数据
        QPair<QString, QVector<double>> m_x{}; // 存的是原始数据
        QPair<QString, QVector<double>> m_y{};
        QString m_scanParaName{};                 // 扫描参数名字，不用下标（相同的名字在不同文件中可能是不同的下标）
        QString m_secondScanParaName{};           // 扫描参数名字，不用下标（相同的名字在不同文件中可能是不同的下标）
        Graph2DWindowBase* m_addedGraph{nullptr}; // 曲线添加到了哪个图上
        QCPLayerable* m_curveLineAddress{nullptr};
        TextFileParser* m_reader{nullptr};   // 曲线由哪个reader产生
        int m_scanParaIndex{-1};             // 扫描参数下标
        int m_secondScanParaIndex{-1};       // 扫描参数下标
        QList<QString> m_commonFixedNames{}; // 共同的可用作变量轴的列名
        QVector<double> m_otherKeyData{};    // 其他key对应的数值，每个曲线对于每个key只对应一个值
        int m_valueIndex{-1};                // 对应的value下标
        int m_valueComponent{0};             // value的分量
        int m_isNormalized{0};               // -1：未定义,部分选中；0，没有取；其他：取了归一化
        int m_isDB{0};                       // 界面上的db选择框情况
        int m_isDBState{0};                  // 幅度相位情况下真实的db选择情况
        //-1：未定义；0，没有取；其他：取了
        GraphType m_graphType = GraphType::None;
        bool m_isOnlyShow = false; // 是否为仅可显示标识，设置为true后，相关曲线不可能更改任何数据，只可显示
        QVector<std::array<QVector<double>, 3>> m_animationDataList;
        int m_currentAnimationIndex{0};
        bool m_enableMathematicalOperations = false;
        QString m_calculationFormula; // 公式编辑框中输入的公式
        QString m_curveName = "";
        bool m_isImport = false;
        QStringList m_geometryFileName;
        QString m_dataSources;
        int m_fieldType = 0; // 域类型：1：时域；2频域；0：无
        QString m_unit; //热力图动图使用的
        QList<double> m_VarValueList;
        int m_lastFrameIndexBeforeExportAnimation{0}; // 动图导出前的最后一帧
        QStandardItem* m_projectTreeSourceItem = nullptr;//工程树中曲线对应的item
        QStandardItem* m_sidebarItem = nullptr;//侧边栏名称列表对应的item

        bool m_isFromStandardFile = false;
        QString m_standardCurveParserFileName = "";



    public:

        bool m_isNewData = false;  // 是否为新数据标识，设置为true后，相关曲线不可更改固定值等，可以db、归一化、公式编辑，后续数据计算不再从TextFileParser中去获取原始数据，直接使用xData与yData
        //某些新生成的曲线（如波形分析等）不能重新从reader中获取单位，因此必须记录曲线产生之前的单位
        int m_xAxisType{ -1 };
        QString m_xAxisUnit = ""; //x单位
        std::tuple<int, int, QString> m_yAxisUnit;

        // 新增
        //============================
        inline void setLineChartCenterSettingData(LineChartCenterSettingData* CenterSettingData) { m_centerSettingData = CenterSettingData; }
        inline LineChartCenterSettingData* getLineChartCenterSettingData() { return m_centerSettingData; }
        LineChartCenterSettingData* m_centerSettingData;

        inline void setPolarGraphCenterSettingData(PolarCoordinateGraphCenterSettingData* CenterSettingData) { m_polarCoordinateGraphCenterSettingData = CenterSettingData; }
        inline PolarCoordinateGraphCenterSettingData* getPolarGraphCenterSettingData() { return m_polarCoordinateGraphCenterSettingData; }
        PolarCoordinateGraphCenterSettingData* m_polarCoordinateGraphCenterSettingData;

        inline void setDataHeatGraph2DSettings(DataHeatGraph2DSettings* CenterSettingData) { m_dataHeatGraph2DSettings = CenterSettingData; }
        inline DataHeatGraph2DSettings* getDataHeatGraph2DSettings() { return m_dataHeatGraph2DSettings; }
        DataHeatGraph2DSettings* m_dataHeatGraph2DSettings;

        inline void setCurvePropertyData(Style2D_DataProperty* CurvePropertyData) { m_curveSettingData = CurvePropertyData; }
        inline Style2D_DataProperty* getCurvePropertyData() { return m_curveSettingData; }
        Style2D_DataProperty* m_curveSettingData{nullptr};




    };
} // namespace pst
#endif
